using System.Text.Json;
using System.Text.Json.Serialization;
using System.Web;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using RestaurantFinder.Core.Models;
using RestaurantFinder.Core.Services;

namespace RestaurantFinder.Infrastructure.Services;

/// <summary>
/// 高德地图服务实现
/// </summary>
public class GaodeMapService : IGaodeMapService
{
    private readonly HttpClient _httpClient;
    private readonly IConfiguration _configuration;
    private readonly ILogger<GaodeMapService> _logger;
    private readonly string? _apiKey;
    private const string BaseUrl = "https://restapi.amap.com/v3";

    public GaodeMapService(
        HttpClient httpClient, 
        IConfiguration configuration, 
        ILogger<GaodeMapService> logger)
    {
        _httpClient = httpClient;
        _configuration = configuration;
        _logger = logger;
        _apiKey = _configuration["GaodeMap:ApiKey"];
        
        if (string.IsNullOrEmpty(_apiKey))
        {
            _logger.LogWarning("高德地图API密钥未配置，请在appsettings.json中添加 GaodeMap:ApiKey");
        }
        else
        {
            _logger.LogInformation("高德地图API已配置，密钥长度: {KeyLength}", _apiKey.Length);
        }
    }

    /// <summary>
    /// 搜索指定位置附近的POI
    /// </summary>
    public async Task<GaodePoiResponse> SearchPoisAsync(RestaurantSearchRequest request)
    {
        if (string.IsNullOrEmpty(_apiKey))
        {
            throw new InvalidOperationException("高德地图API密钥未配置");
        }

        try
        {
            var url = BuildSearchUrl(request);
            _logger.LogInformation("正在调用高德地图API: {Url}", url);

            var response = await _httpClient.GetAsync(url);
            response.EnsureSuccessStatusCode();

            var jsonContent = await response.Content.ReadAsStringAsync();
            _logger.LogDebug("高德地图API响应: {Response}", jsonContent);

            var jsonOptions = new JsonSerializerOptions
            {
                PropertyNameCaseInsensitive = true,
                DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
            };

            var poiResponse = JsonSerializer.Deserialize<GaodePoiResponse>(jsonContent, jsonOptions);

            if (poiResponse?.Status != "1")
            {
                var errorMsg = $"高德地图API调用失败: Status={poiResponse?.Status ?? "null"}, Info={poiResponse?.Info ?? "null"}";
                _logger.LogWarning(errorMsg);
                
                // 记录完整的API响应以便调试
                if (jsonContent.Length < 1000)
                {
                    _logger.LogDebug("完整API响应: {Response}", jsonContent);
                }
                
                return new GaodePoiResponse();
            }

            _logger.LogInformation("成功获取 {Count} 个POI", poiResponse.Pois.Count);
            return poiResponse;
        }
        catch (JsonException jsonEx)
        {
            _logger.LogError(jsonEx, "高德地图API响应JSON解析失败");
            return new GaodePoiResponse(); // 返回空结果而不是抛出异常
        }
        catch (HttpRequestException httpEx)
        {
            _logger.LogError(httpEx, "高德地图API网络请求失败");
            throw;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "调用高德地图API时发生未知错误");
            throw;
        }
    }

    /// <summary>
    /// 将高德地图POI转换为餐厅对象
    /// </summary>
    public List<Restaurant> ConvertToRestaurants(List<GaodePoi> pois, Location userLocation)
    {
        var restaurants = new List<Restaurant>();

        foreach (var poi in pois)
        {
            try
            {
                // 解析位置坐标
                var locationParts = poi.Location.Split(',');
                if (locationParts.Length != 2 ||
                    !double.TryParse(locationParts[1], out var latitude) ||
                    !double.TryParse(locationParts[0], out var longitude))
                {
                    _logger.LogWarning("无效的位置格式: {Location}", poi.Location);
                    continue;
                }

                var restaurantLocation = new Location(latitude, longitude);

                // 解析距离
                if (!int.TryParse(poi.Distance, out var distance))
                {
                    distance = (int)CalculateDistance(userLocation, restaurantLocation);
                }

                // 获取评分信息
                var bizExt = poi.GetBizExt();
                double? rating = null;
                if (bizExt?.Rating != null && double.TryParse(bizExt.Rating, out var ratingValue))
                {
                    rating = ratingValue;
                }

                // 获取电话号码
                var phoneNumber = poi.GetTel();

                var restaurant = new Restaurant(
                    poi.Id,
                    poi.Name,
                    poi.Address,
                    restaurantLocation,
                    distance,
                    rating,
                    phoneNumber
                );

                restaurants.Add(restaurant);
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "转换POI失败: {PoiName}", poi.Name);
            }
        }

        return restaurants.OrderBy(r => r.Distance).ToList();
    }

    /// <summary>
    /// 构建搜索URL
    /// </summary>
    private string BuildSearchUrl(RestaurantSearchRequest request)
    {
        var baseUrl = _configuration["GaodeMap:BaseUrl"] ?? BaseUrl;
        var queryParams = new Dictionary<string, string>
        {
            ["key"] = _apiKey!,
            ["keywords"] = HttpUtility.UrlEncode(request.Keyword),
            ["location"] = $"{request.Location.Longitude},{request.Location.Latitude}",
            ["radius"] = request.RadiusInMeters.ToString(),
            ["offset"] = request.MaxResults.ToString(),
            ["page"] = request.Page.ToString(),
            ["extensions"] = "base",
            ["output"] = "json",
            ["types"] = "050000" // 餐饮服务类型
        };

        var queryString = string.Join("&", queryParams.Select(kvp => $"{kvp.Key}={kvp.Value}"));
        var url = $"{baseUrl}/place/around?{queryString}";
        
        _logger.LogDebug("构建的搜索URL: {Url}", url);
        return url;
    }

    /// <summary>
    /// 计算两点间距离（哈弗辛公式）
    /// </summary>
    private static double CalculateDistance(Location point1, Location point2)
    {
        const double earthRadius = 6371000; // 地球半径（米）
        
        var lat1Rad = point1.Latitude * Math.PI / 180;
        var lat2Rad = point2.Latitude * Math.PI / 180;
        var deltaLatRad = (point2.Latitude - point1.Latitude) * Math.PI / 180;
        var deltaLngRad = (point2.Longitude - point1.Longitude) * Math.PI / 180;

        var a = Math.Sin(deltaLatRad / 2) * Math.Sin(deltaLatRad / 2) +
                Math.Cos(lat1Rad) * Math.Cos(lat2Rad) *
                Math.Sin(deltaLngRad / 2) * Math.Sin(deltaLngRad / 2);
        
        var c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
        
        return earthRadius * c;
    }
} 